(function (pluginLoad, $, window, document, undefined) {

    // 无限滚动
    function RollSlider (opt){ this.init(opt) }
    RollSlider.prototype = {
        // 构造函数指向自身
        constructor: RollSlider,
        // 获取DOM
        _$: function (str){
            return typeof str === 'string'
                ? document.querySelector(str)
                : str
        },
        // 覆盖默认参数
        _extend: function (def, opt){
            for(var key in def){
                if(opt.hasOwnProperty(key)){
                    def[key] = opt[key]
                }
            }
            return def
        },
        // 初始化
        init: function (opt) {
            opt = opt || {};
            // 默认参数
            var defaultOpt = {
                el: '' // 目标元素
                ,auto: true // 是否自动运行
                ,speed: 1  // 速度，值越小越慢。
            };

            this.opt = this._extend(defaultOpt, opt);
            this.opt.el = this._$(this.opt.el);
            this.opt.sliderEl = this.opt.el.firstElementChild;
            this.opt.isEnough = false; // 默认数量不足

            if(!this.opt.el){
                console.warn('未绑定元素');
                return
            }

            this.isLoaded();

            var _this = this;
            // 暂停
            this.opt.el.onmouseenter = function () {
                _this.opt.isEnough && _this.stop()
            };
            // 运行
            this.opt.el.onmouseleave = function () {
                _this.opt.isEnough && _this.run()
            }
        },
        // 定时循环，直到加载完DOM后再运行
        isLoaded: function (){
            var _this = this;
            var hasDOM = setInterval(function () {
                if(_this.opt.sliderEl.firstElementChild){

                    var childNodes = _this.childNodes(_this.opt.sliderEl.childNodes),
                        childNodesLen = childNodes.length,
                        lastNode = childNodes[childNodesLen - 1];
                    _this.opt.width = _this.opt.el.getBoundingClientRect().width || 0; // 容器宽度
                    _this.opt.pos_left = _this.opt.el.getBoundingClientRect().left || 0; // 容器左侧位置
                    _this.opt.pos_right = _this.opt.el.getBoundingClientRect().right || 0; // 容器右侧位置
                    _this.opt.offset_right = lastNode.getBoundingClientRect().right || 0; // 容器内最后一个子元素右侧偏移量
                    _this.opt.pos_reset = window.getComputedStyle(lastNode).getPropertyValue('margin-right') || '0px';  //子元素margin-right偏移量，用来reset值

                    _this.opt.isEnough = _this.isEnoughDOM();
                    if(_this.opt.isEnough){
                        _this.opt.auto && _this.run();
                        _this.opt.auto && _this.cloneDOM()
                    }
                    clearInterval(hasDOM)
                }
            }, 50)
        },
        // 容器元素数量不够时，不运行
        isEnoughDOM: function (){
            var childNodes = this.childNodes(this.opt.sliderEl.childNodes),
                childNodesLen = childNodes.length,
                lastNode = childNodes[childNodesLen - 1];
            if(lastNode.getBoundingClientRect().right - this.opt.pos_left <= this.opt.width){
                return false
            }
            return true
        },
        // 处理childNodes
        childNodes: function (nodes){
            var filterNodes = Array.prototype.slice.call(nodes).filter(function (node) {
                return node.nodeType === 1  // html元素
            });
            return filterNodes || []
        },
        // 克隆元素，运行一次
        cloneDOM: function (){
            var _this = this,
                childNodes = _this.opt.sliderEl.childNodes;
            if(_this.opt.isClone) return;

            Array.prototype.slice.call(childNodes).forEach(function (node) {
                var cloneNode = node.cloneNode(true);
                _this.opt.sliderEl.appendChild(cloneNode);
            });
            _this.opt.isClone = true
        },
        // 容器复原
        reset: function (){
            var el = this.opt.sliderEl,
                left = parseFloat(el.style.left) || 0;
            if(left + (this.opt.offset_right - this.opt.pos_left) <= 0){
                el.style.left = this.opt.pos_reset // 这里根据item的margin-right来取值
            }
        },
        // 运行
        run: function () {

            this.reset(); //

            var el = this.opt.sliderEl,
                left = parseFloat(el.style.left) || 0;
            var _this = this;

            el.style.left = (left - this.opt.speed) + 'px';
            this.opt.requestID = requestAnimationFrame(this.run.bind(_this));
        },
        // 暂停
        stop: function () {
            var _this = this;
            cancelAnimationFrame(_this.opt.requestID)
        }
    };

    // 三级联动 下拉菜单联动（依赖jquery.selectmenu.js）
    function ChainPicker (opt){
        this.init(opt)
    }
    ChainPicker.prototype = {
        // 构造函数指向自身
        constructor: ChainPicker,
        // 初始化
        init: function (opt){
            opt = opt || {};
            this.opt = {};

            if($('.picker_container').length){
                console.warn('已创建picker');
                return false
            }
            // 3：三级联动  2：二级联动  1：一级联动
            this.opt.level = opt.level || 3;
            if(this.opt.level > 3 || this.opt.level < 1){
                console.warn('level取值在1-3');
                return false
            }

            // 赋值数据
            this.opt.first = opt.data.first;
            this.opt.second = opt.data.second;
            this.opt.third = opt.data.third;

            // msg
            this.opt.msg = opt.msg;

            // 设置各级宽度
            opt.style = opt.style || {};
            this.opt.style = {
                first: opt.style.first || 200,
                second: opt.style.second || 200,
                third: opt.style.third || 200
            };

            // 显示字段
            this.opt.showField = opt.showField;
            this.opt.keyField = opt.keyField;
            this.opt.chainField = opt.chainField;

            // 是否多选（有且只能是三级）
            this.opt.multiple = opt.multiple || {};

            // 点击元素
            this.opt.elem = opt.elem;

            // 取值目标元素
            this.opt.targetElem = opt.targetElem || opt.elem;

            this.opt.msgTempt = (typeof opt.msgTempt === 'function' && opt.msgTempt()) || window.alert;

            // 创建容器
            this.createElem(() => {
                this.opt.$first = $('.pickerFirst');
                this.opt.$second = $('.pickerSecond');
                this.opt.$third = $('.pickerThird');
                this.loadFirst()
            });

            var _this = this;

            // body绑定click事件
            document.body.addEventListener('click', handleClick, false);

            // 处理click事件
            function handleClick (e){
                var $tar = $(e.target);
                if(e.target === _this.opt.elem || $tar.hasClass('picker_container')){
                    return null
                }
                // 确认picker数据
                if($tar.hasClass('pickerConfirm')){
                    _this.confirm()
                }
                // 移除picker DOM元素
                if($tar.hasClass('pickerCancel') || !$tar.parents('.picker_container').length){
                    _this.removeElem();
                    document.body.removeEventListener('click', handleClick, false)
                }
            }
        },
        // 确认选择
        confirm: function (){
            var showMsg = this.opt.msgTempt || window.alert,
                level = +this.opt.level;
            var first =  this.opt.$first.selectMenuValues(),
                second =  this.opt.$second.selectMenuValues(),
                third =  this.opt.$third.selectMenuValues();
            // 多选长度限制
            if(this.opt.multiple.on && this.opt.multiple.length < third.length){
                showMsg(`多选内容最多选择${this.opt.multiple.length}项`, {icon: 5});
                return false
            }
            // 分级，判断值
            if(!first.length){
                showMsg('请选择' + this.opt.msg.first, {icon: 5});
                return false
            }else{
                if(level === 2){
                    if(!second.length && this.opt.$second.find('.sm_message_box').length < 1){
                        showMsg('请选择' + this.opt.msg.second, {icon: 5});
                        return false
                    }
                }
                if(level === 3){
                    if(second.length){
                        if(!third.length && this.opt.$third.find('.sm_message_box').length < 1){
                            showMsg('请选择' + this.opt.msg.third, {icon: 5});
                            return false
                        }
                    }else{
                        if(this.opt.$second.find('.sm_message_box').length < 1){
                            showMsg('请选择' + this.opt.msg.second, {icon: 5});
                            return false
                        }
                    }
                }
            }
            this.transTargetElem(first,second,third)
        },
        // 转换target元素，当传入 input、textarea、select时赋值value，否则赋值html
        transTargetElem: function (...params){
            var _this = this,
                targetElem = _this.opt.targetElem[0] || _this.opt.targetElem,
                result = '';
            params.forEach(function (item, index){
                if(index === 2 && _this.opt.multiple.on && item.length > 1){
                    var itemStr = '';
                    item.forEach(item1 => {
                        itemStr += item1[_this.opt.showField] + ','
                    });
                    itemStr = itemStr.slice(0, -1);
                    result += itemStr
                }else{
                    result += item[0] && (item[0][_this.opt.showField] + "-") || ''
                }
            });
            result = result.slice(0, -1);
            if(targetElem.nodeName === 'INPUT' || targetElem.nodeName === 'SELECT' || targetElem.nodeName === 'TEXTAREA'){
                targetElem.value = result
            }else{
                targetElem.innerHTML = result
            }
            targetElem.setAttribute('title', result);
            $('.pickerCancel').click()
        },
        // 移除picker容器
        removeElem: function (){
            $('.picker_container').remove();
        },
        // 创建picker容器
        createElem: function (callback){
            var elem = this.opt.elem,
                x = elem.getBoundingClientRect().left || 0,
                y = ((elem.getBoundingClientRect().top + $(elem).height() + 5) + $(window).scrollTop()) || 0;
            var level = +this.opt.level,
                domLevel = '';
            switch (level){
                case 1:
                    domLevel += `<div class="pickerFirst" style="width: ${this.opt.style.first}px"></div>`;
                    break;
                case 2:
                    domLevel += `<div class="pickerFirst" style="width: ${this.opt.style.first}px"></div>
                                 <div class="pickerSecond"></div>`;
                    break;
                case 3:
                    domLevel += `<div class="pickerFirst" style="width: ${this.opt.style.first}px"></div>
                                 <div class="pickerSecond"></div>
                                 <div class="pickerThird"></div>`;
                    break
            }
            var dom =  `<div class="picker_container" style="left: ${x}px; top: ${y}px;">
                            ${domLevel}
                            <div class="picker_container_btn clearfix">
                                <button class="layui-btn pickerConfirm" type="button">确认</button>
                                <button class="layui-btn layui-btn-primary pickerCancel" type="button">取消</button>
                            </div>
                        </div>`;
            $('body').append(dom);
            callback()
        },
        // 一级
        loadFirst: function (){
            var _this = this;
            this.opt.$first.selectMenu({
                showField: _this.opt.showField,
                keyField: _this.opt.keyField,
                title: _this.opt.msg.first || '一级',
                search: false,
                embed : true,
                orderBy: false,
                data: _this.opt.first,
                eSelect: function(){
                    _this.opt.$second.selectMenuClear();
                    _this.opt.$third.selectMenuClear();
                    _this.loadSecond()
                }
            })
        },
        // 二级
        loadSecond: function (){
            var _this = this,
                $first = _this.opt.$first;
            this.opt.$second.width(this.opt.style.second);
            this.opt.$second.selectMenu({
                showField: _this.opt.showField,
                keyField: _this.opt.keyField,
                title: _this.opt.msg.second || '二级',
                search: false,
                embed : true,
                orderBy: false,
                data: function(){
                    var arr = [],
                        values = $first.selectMenuValues();
                    if(values && values.length){
                        $.each(_this.opt.second, function(i,row){
                            if(row[_this.opt.chainField] === values[0][_this.opt.keyField]) {arr.push(row)}
                        })
                    }

                    arr.length ? _this.opt.$second.removeClass('hidden') : _this.opt.$second.addClass('hidden');

                    return arr
                },
                eSelect: function(){
                    _this.opt.$third.selectMenuClear();
                    _this.loadThird()
                }
            })
        },
        // 三级
        loadThird: function (){
            var _this = this,
                $second = _this.opt.$second;
            this.opt.$third.width(this.opt.style.third);
            this.opt.$third.selectMenu({
                showField: _this.opt.showField,
                keyField: _this.opt.keyField,
                title: _this.opt.msg.third || '三级',
                multiple: _this.opt.multiple.on || false,
                search: false,
                embed : true,
                orderBy: false,
                data: function(){
                    var arr = [],
                        values = $second.selectMenuValues();
                    if(values && values.length){
                        $.each(_this.opt.third, function(i,row){
                            if(row[_this.opt.chainField] === values[0][_this.opt.keyField]) {arr.push(row)}
                        })
                    }

                    arr.length ? _this.opt.$third.removeClass('hidden') : _this.opt.$third.addClass('hidden');

                    return arr
                },
                eSelect: function(res){
                    if(_this.opt.multiple.on && res.length > _this.opt.multiple.length){
                        _this.opt.msgTempt(`多选内容最多选择${_this.opt.multiple.length}项`, {icon: 5})
                    }
                }
            })
        }
    };

    // 插件集合
    var plugin = {
        rollSlider: function (config) {
            return new RollSlider(config)
        },
        chainPicker: function (config) {
            return new ChainPicker(config)
        }
    };

    window.pluginLoad = Object.assign(pluginLoad, plugin)

})(window.pluginLoad || {}, jQuery, window, document);